package com.dwy2002.appointment.config;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
import org.springframework.amqp.rabbit.config.RetryInterceptorBuilder;
import org.springframework.amqp.rabbit.config.SimpleRabbitListenerContainerFactory;
import org.springframework.amqp.rabbit.connection.ConnectionFactory;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.amqp.rabbit.retry.RejectAndDontRequeueRecoverer;
import org.springframework.amqp.support.converter.Jackson2JsonMessageConverter;
import org.springframework.amqp.support.converter.MessageConverter;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.retry.interceptor.RetryOperationsInterceptor;

/**
 * RabbitMQTopic配置类
 *
 * @author 杜伟毅
 * @version 1.0
 * @since 2025/03/22
 */
@Configuration
public class RabbitConfig {

    @Bean
    public RabbitTemplate rabbitTemplate(ConnectionFactory connectionFactory) {
        RabbitTemplate template = new RabbitTemplate(connectionFactory);
        template.setMessageConverter(jsonMessageConverter());
        return template;
    }

    /**
     * 消费者监听器容器工厂配置（整合重试机制）
     *
     * @author 杜伟毅
     * @since 2025/3/23 0023 16:35
     */
    @Bean
    public SimpleRabbitListenerContainerFactory rabbitListenerContainerFactory(ConnectionFactory connectionFactory, RetryOperationsInterceptor retryInterceptor) {
        SimpleRabbitListenerContainerFactory factory = new SimpleRabbitListenerContainerFactory();
        factory.setConnectionFactory(connectionFactory);
        factory.setAdviceChain(retryInterceptor); // 绑定重试拦截器
        factory.setMessageConverter(jsonMessageConverter()); // 设置消息转换器（如处理JSON）
        return factory;
    }


    /**
     * 重试策略配置
     *
     * @author 杜伟毅
     * @since 2025/3/23 0023 16:35
     */
    @Bean
    public RetryOperationsInterceptor retryInterceptor() {
        return RetryInterceptorBuilder.stateless()
                .maxAttempts(3) // 最大重试次数（含首次）
                .backOffOptions(1000, 2.0, 5000) // 初始间隔1秒，倍数2，最大间隔5秒
                .recoverer(new RejectAndDontRequeueRecoverer()) // 最终拒绝并不重新入队
                .build();
    }

    /**
     * JSON消息转换器（若消息体为JSON）
     *
     * @author 杜伟毅
     * @since 2025/3/23 0023 16:35
     */
    @Bean
    public MessageConverter jsonMessageConverter() {
        ObjectMapper objectMapper = new ObjectMapper();
        objectMapper.registerModule(new JavaTimeModule());
        return new Jackson2JsonMessageConverter(objectMapper);
    }


    /*最终效果
正常流程：消息进入 enrollment.request.queue → 消费者最多重试3次 → 成功则确认，失败则拒绝。
异常流程：重试耗尽后，消息被拒绝 → 路由到死信队列 dlx.queue → 可单独处理死信消息（如人工介入或自动修复）。*/
}
